using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using OhioState.AssetManaged;
using OhioState.Graphics;
using OhioState.Graphics.Proxy;



namespace OhioState.Controls
{
    public partial class LayersControl : UserControl
    {

        //
        // Pointer to the asset manager instance
        //
        private AssetManager assetMan;
        //
        // Desired Type - "" = everything
        //
        Type type;
        //
        // Preview Size Property
        //
        Size previewSize;
        int previewPadding;
        //
        // List of templates
        //
        List<LayerProxy> templates;
        List<ViewProxy> viewProxies;

        //
        // Event for changing selection and notifying about items being updated
        //
        public event IAssetManagedListHandler SelectedEvent;
        public event IAssetManagedHandler UpdatedEvent;
        //
        // Asset Manager events
        //
        private IAssetManagedHandler assetManAddItemEvent;
        private IAssetManagedHandler assetManRemoveItemEvent;
        //
        // Event to trigger invalidate
        //
        public event IAssetManagedHandler ChangedEvent;
        //
        // Event for monitoring changes of the current layer
        //
        //IAssetManagedHandler updateEvent;
        private LayerProxy layer;
        //
        // Event helper for firing events
        //
        protected EventsStrategyAbstract _eventsHelper;
        public LayersControl()
        {
            InitializeComponent();
            assetMan = null;
            templates = new List<LayerProxy>();
            viewProxies = new List<ViewProxy>();

           
            //layers = new List<LayerProxy>();
            _eventsHelper = new EventsStrategyAsync();
            layer = null;
            SelectedEvent += new IAssetManagedListHandler(UserControl1_SelectedEvent);
            UpdatedEvent += new IAssetManagedHandler(UserControl1_UpdatedEvent);
            //SelectedLayer += new LayerSelected(layerControl_SelectedLayer);
            //
            // set size defaults
            //
            PreviewColumnOn = true;
            previewPadding = 2;
            PreviewSize = new Size(44, 14);


            dataGridView2.Columns["listColumn"].DisplayIndex = 0;
            dataGridView2.Columns["DrawablesColumn"].DisplayIndex = 1;
            dataGridView2.Columns["MoveToColumn"].DisplayIndex = 2;
            dataGridView2.Columns["DatColumn"].DisplayIndex = 3;

            dataGridView1.Columns["CheckColumn"].DisplayIndex = 0;
            dataGridView1.Columns["PreviewColumn"].DisplayIndex = 1;
            dataGridView1.Columns["NameCol"].DisplayIndex = 2;



            Init(typeof(LayerProxy));
            //
            // Create default layers
            //
            //SetupDefaultLayers();
            //BuiltTemplateDropDown();
            //BuildBackGround();


        }

        public void SetViewProxy(ViewProxy view)
        {
            //ViewProxy singleView = AssetManager.Instance.GetItem(typeof(ViewProxy),"Main View") as ViewProxy;
            viewProxies.Add(view);

        }
        public void Init(Type desired_type)
        {
            //
            // Determine if the asset manager pointer needs updated
            //
            if (assetMan == null)
            {
                //
                // Get a pointer to the intstance of the asset manager
                //
                assetMan = AssetManager.Instance;

                //
                // Set up event handlers for add and remove items
                //
                assetManAddItemEvent = new IAssetManagedHandler(layerManager_AddItemEvent);
                assetMan.AssetAdded += assetManAddItemEvent;
                assetManRemoveItemEvent = new IAssetManagedHandler(layerManager_RemoveItemEvent);
                assetMan.AssetRemoved += assetManRemoveItemEvent;
            }
            type = desired_type;
            // Ensure the data grid is clear of anything that may have been in it before
            dataGridView1.Rows.Clear();

            
            //
            // Populate data grid view
            //
            //List<IAssetManaged> list = assetMan.GetItem(type);
            //foreach (IAssetManaged obj in list)
            //{
            //    layerManager_AddItemEvent_thisThread(obj);
            //}


        }

        #region Setup default layers

        private void SetupDefaultLayers()
        {
        }
        #endregion


        //Setup the drop down list of all templates
        // Clear the Drop down menu and then add each item from the template list to the
        // drop down menu.  Create preview icons as well.

        private void BuiltTemplateDropDown()
        {
            newToolStripButton.DropDownItems.Clear();

            //LayerProxy lay = new LayerProxy("Background");

            //Camera camera = AssetManager.Instance.Find(typeof(Camera), "MainCamera") as Camera;
            //if (camera != null)
            //{
            //    lay.Camera = camera;
            //}
           
            ////IAssetManaged obj = assetMan.AddItem(lay);
            ////lay.Image = new Bitmap("background.bmp");
            ////lay.Image = new Bitmap("Winter.JPG");
            //lay.Image = new Bitmap("C:\\Documents and Settings\\All Users\\Documents\\My Pictures\\Sample Pictures\\background.bmp");
            //templates.Add(lay);

            foreach (LayerProxy obj in templates)
            {
                Bitmap b = obj.Image;
                //for (int i = 0; i < 64; i++)
                //    for (int j = 0; j < 64; j++)
                //        b.SetPixel(i, j, Color.BlueViolet);

                //obj.Preview(b);
                newToolStripButton.DropDownItems.Add(obj.Name, b, CreateNewFromTemplate);

            }
        }



        #region Public properties
        //
        // Public properties
        //  - Enable or disable Preview column in the data grid view
        //  - Change Row height of data grid view
        //  - Change the size of the preview image
        //  - Modify the header text: default is "Name"
        //  - Toggle the column headers on and off
        //  - Toggle ability to rename items
        //  - Toggle auto selection
        //
        public bool PreviewColumnOn
        {
            get { return dataGridView1.Columns["PreviewColumn"].Visible; }
            set { dataGridView1.Columns["PreviewColumn"].Visible = value; }
        }
        public int RowHeight
        {
            get { return dataGridView1.RowTemplate.Height; }
            set { dataGridView1.RowTemplate.Height = value; }
        }
        public int PreviewPadding
        {
            get { return previewPadding; }
            set
            {
                previewPadding = value;
                UpdatePreviewSize();
            }
        }
        public Size PreviewSize
        {
            get { return previewSize; }
            set
            {
                previewSize = value;
                UpdatePreviewSize();
            }
        }
        public String ColumnHeaderText
        {
            get { return dataGridView1.Columns["NameCol"].HeaderText; }
            set { dataGridView1.Columns["NameCol"].HeaderText = value; }
        }
        public bool ColumnHeadersVisible
        {
            get { return dataGridView1.ColumnHeadersVisible; }
            set { dataGridView1.ColumnHeadersVisible = value; }
        }
        public bool ReadOnly
        {
            get { return dataGridView1.ReadOnly; }
            set { dataGridView1.ReadOnly = value; }
        }
        //public bool AutoSelect
        //{
        //    get { return autoSelect; }
        //    set { autoSelect = value; }
        //}
        public bool MultiSelect
        {
            get { return dataGridView1.MultiSelect; }
            set { dataGridView1.MultiSelect = value; }
        }
        //
        // helper function to help update preview size
        //
        private void UpdatePreviewSize()
        {
            RowHeight = previewSize.Height + 2 * previewPadding;
            dataGridView1.Columns["PreviewColumn"].Width = previewSize.Width + 2 * previewPadding;
        }
        #endregion

        //
        // Select the row of the data grid view that this object is in.
        //  The result of this is that multiple rows can be selected as this
        //  only adds the the list of currently selected rows.
        //
        public void SelectItem(IAssetManaged obj)
        {
            //if (assetMan != null)
            //{
            //    foreach (DataGridViewRow row in dataGridView1.Rows)
            //    {
            //        IAssetManaged data = (IAssetManaged)row.Cells["DataColumn"].Value;
            //        if (data == obj)
            //        {
            //            row.Selected = true;
            //            break;
            //        }
            //    }
            //}
        }
        //
        // Select only the row of the data grid view that this object is in.
        //  The result of this is that only one row is selected at max.
        //
        public void SelectOneItem(IAssetManaged obj)
        {
            //ClearSelection();
            //SelectItem(obj);
        }
        //
        // Deselect every item
        //
        public void ClearSelection()
        {
            dataGridView1.ClearSelection();
        }

        //
        // Returns the currently selected item or null if there is none.
        //
        public List<IAssetManaged> GetSelected()
        {
            List<IAssetManaged> list = new List<IAssetManaged>();
            if (assetMan != null)
            {
                foreach (DataGridViewRow row in dataGridView1.SelectedRows)
                {
                    IAssetManaged obj = (IAssetManaged)row.Cells["DataColumn"].Value;
                    // Apparently this can sometimes be null... wtf?
                    if (obj != null)
                        list.Add(obj);
                }
            }

            return list;
        }

        #region AssetManager Subscription Services?
        //
        // Event handler that gets triggered when an object is added to the asset manager.
        //  This function first checks if it is the correct type of object before adding
        //  it to the data grid view.  If the object is Previewable, it will get a preview and
        //  set up the necessary events to update the preview after changes.
        //
        public void layerManager_AddItemEvent_thisThread(IAssetManaged obj)
        {
            if (assetMan != null)
            {
                //
                // Determine if this is an item that we want.  Check the type as well as base types.
                //
                bool correctType = false;
                if (type == null)
                {
                    correctType = true;
                }
                else
                {
                    Type itemType = obj.GetType();
                    while (itemType != null)
                    {
                        if (itemType == type)
                        {
                            correctType = true;
                            break;
                        }
                        itemType = itemType.BaseType;
                    }

                    if (correctType == false)
                    {
                        itemType = obj.GetType();
                        // Specify the TypeFilter delegate that compares the 
                        // interfaces against filter criteria.
                        TypeFilter myFilter = new TypeFilter(MyInterfaceFilter);
                        String[] myInterfaceList = new String[3] 
                            {
                            "OhioState.Graphics.IShape",
                            "OhioState.Graphics.IPlane",
                            "OhioState.Graphics.IDrawable"};
                        for (int index = 0; index < myInterfaceList.Length; index++)
                        {
                            Type[] myInterfaces = itemType.FindInterfaces(myFilter,
                                myInterfaceList[index]);
                            if (myInterfaces.Length > 0)
                            {
                                for (int j = 0; j < myInterfaces.Length; j++)
                                {
                                    itemType = myInterfaces[j];
                                    if (itemType == type)
                                    {
                                        correctType = true;
                                        break;
                                    }
                                }
                                if (correctType == true)
                                    break;
                            }
                        }

                    }



                }
                if (correctType)
                {
                    int row = dataGridView1.Rows.Add();
                    dataGridView1.Rows[row].Cells["NameCol"].Value = obj.Name;
                    DataGridViewImageCell imageCell = new DataGridViewImageCell();
                    imageCell.ValueType = typeof(Bitmap);
                    imageCell.Value = (Bitmap)((LayerProxy)obj).Image;
                    dataGridView1.Rows[row].Cells["PreviewColumn"] = imageCell;
                    dataGridView1.Rows[row].Cells["DataColumn"].Value = obj;
                    dataGridView1.Rows[row].Cells["CheckColumn"].Value = true;

                    //
                    // Get a preview of the object if it is IPreviewable.
                    //
                    if (obj.GetType().GetInterface("IPreviewable") != null)
                    {
                        try
                        {
                            Bitmap bitmap = new Bitmap(previewSize.Width, previewSize.Height);
                            //((IPreviewable)obj).Preview(bitmap);
                            //
                            // Get the constructor of the object and invoke it
                            //
                            Type objType = obj.GetType();
                            Type[] types = new Type[1];
                            types[0] = objType;
                            // Get the constructor that takes an integer as a parameter.
                            ConstructorInfo constructorInfoObj = objType.GetConstructor(types);
                            if (constructorInfoObj != null)
                            {
                                object[] args = new object[1];
                                args[0] = obj;
                                IPreviewable temp = (IPreviewable)constructorInfoObj.Invoke(args);
                                if (temp != null)
                                {
                                    temp.Preview(bitmap);
                                    ((DataGridViewImageCell)dataGridView1.Rows[row].Cells["PreviewColumn"]).Value = bitmap;
                                }
                            }
                        }
                        catch { }
                    }
                    else
                    {
                        dataGridView1.Rows[row].Cells["EventHandlerColumn"].Value = null;
                    }
                    //
                    // Set up event handler call back to redraw the preview of the object
                    //
                    IAssetManagedHandler changed = new IAssetManagedHandler(iAssetManaged_UpdateChangedEvent);
                    obj.AddChangedEventHandler(changed);
                    dataGridView1.Rows[row].Cells["EventHandlerColumn"].Value = changed;
                    // select the proper row                    
                    //ClearSelection();
                    //dataGridView1.Rows[row].Selected = true;
                    _eventsHelper.Fire(UpdatedEvent, obj);
                    //if (UpdatedEvent != null)
                    //{
                    //    Delegate[] updateSubscribers = UpdatedEvent.GetInvocationList();
                    //    foreach (Delegate subscriber in updateSubscribers)
                    //    {
                    //        IAssetManagedHandler updateEvent = (IAssetManagedHandler)subscriber;
                    //        try
                    //        {
                    //            if (this.InvokeRequired)
                    //            {
                    //                this.Invoke(updateEvent);
                    //            }
                    //            else
                    //            {
                    //                updateEvent(obj);
                    //            }
                    //        }

                    //        catch { }
                    //    }
                    //}
                }
                
                
                if (obj is IDrawable)
                {
                    populateDrawables();
                    List<IAssetManaged> lay = GetSelected();
                    if (lay.Count > 0)
                    {
                        setActiveDrawables((LayerProxy)lay[0]);
                    }
                }

            }
        }


        public static bool MyInterfaceFilter(Type typeObj, Object criteriaObj)
        {
            if (typeObj.ToString() == criteriaObj.ToString())
                return true;
            else
                return false;
        }
        //
        // Force the event to get called on the proper thread.  The DataGridView complains if you try
        //  to use it on the wrong thread.
        //
        private delegate void LayerAddHandler(IAssetManaged obj);
        public void layerManager_AddItemEvent(IAssetManaged obj)
        {
            //IAssetManagedHandler newEvent = new IAssetManagedHandler(layerManager_AddItemEvent_thisThread);
            LayerAddHandler newEvent = new LayerAddHandler(layerManager_AddItemEvent_thisThread);
            object[] args = new object[1];
            args[0] = obj;

            //
            // We need to make sure these methods are executed on the correct thread.
            //
            try
            {
                if (this.InvokeRequired)
                    this.Invoke(newEvent, args);
                else
                    newEvent(obj);
            }
            catch { }

            // Check if the added item is a drawableProxy (for now ROIBoxProxy)

        }

        //
        // Removes item from data grid view when the remove event is received from the
        //  asset manager.  Update events are also removed.
        //
        public void layerManager_RemoveItemEvent_thisThread(IAssetManaged obj)
        {
            if (assetMan != null)
            {

                foreach (DataGridViewRow row in dataGridView1.Rows)
                {
                    if (row.Cells["DataColumn"].Value == obj)
                    {
                        //
                        // Remove event handler call back to redraw the preview of the object
                        //
                        IAssetManagedHandler changed = (IAssetManagedHandler)row.Cells["EventHandlerColumn"].Value;
                        if (changed != null)
                            obj.RemoveChangedEventHandler(changed);

                        dataGridView1.Rows.Remove(row);

                        _eventsHelper.Fire(UpdatedEvent, obj);
                        break;
                    }
                }
                //if (obj is IDrawable)
                //{
                //    foreach (DataGridViewRow row in dataGridView2)
                //    {
                //        if (row.Cells["DatColumn"].Value == draw)
                //        {
                            
                //        }
                //    }

                //}
                
            }
        }
        //
        // Force the event to get called on the proper thread.  The DataGridView complains if you try
        //  to use it on the wrong thread.
        //
        public void layerManager_RemoveItemEvent(IAssetManaged obj)
        {
            IAssetManagedHandler newEvent = new IAssetManagedHandler(layerManager_RemoveItemEvent_thisThread);
            object[] args = new object[1];
            args[0] = obj;
            //
            // We need to make sure these methods are executed on the correct thread.
            //
            try
            {
                if (this.InvokeRequired)
                    this.Invoke(newEvent, args);
                else
                    newEvent(obj);
            }
            catch { }

        }

        //
        // Update event that gets called when an object is changed.  This is gets a new
        // preview of the obj and displays it in the data grid view.  It also updates the name.
        //
        public void iAssetManaged_UpdateChangedEvent_thisThread(IAssetManaged obj)
        {
            if (assetMan != null)
            {
                foreach (DataGridViewRow row in dataGridView1.Rows)
                {
                    if (row.Cells["DataColumn"].Value == obj)
                    {
                        //
                        // Update the name
                        //
                        row.Cells["NameCol"].Value = obj.Name;
                        DataGridViewImageCell imageCell = new DataGridViewImageCell();
                        imageCell.ValueType = typeof(Bitmap);
                        imageCell.Value = (Bitmap)((LayerProxy)obj).Image;
                        //row.Cells["LayerColumn"] = imageCell;
                        //
                        // Get a preview of the object is it is IPreviewable.
                        //
                        if (obj.GetType().GetInterface("IPreviewable") != null)
                        {
                            try
                            {
                                // We do not need to create a new bitmap, just reuse the old one
                                Bitmap bitmap = (Bitmap)((DataGridViewImageCell)row.Cells["PreviewColumn"]).Value;
                                if (bitmap != null)
                                {
                                    //
                                    // Get the constructor of the object and invoke it
                                    //
                                    Type objType = obj.GetType();
                                    Type[] types = new Type[1];
                                    types[0] = objType;
                                    // Get the constructor that takes an integer as a parameter.
                                    ConstructorInfo constructorInfoObj = objType.GetConstructor(types);
                                    if (constructorInfoObj != null)
                                    {
                                        object[] args = new object[1];
                                        args[0] = obj;
                                        IPreviewable temp = (IPreviewable)constructorInfoObj.Invoke(args);
                                        if (temp != null)
                                        {
                                            //temp.Preview(bitmap);
                                        }
                                    }
                                }
                            }
                            catch { }

                            // This step should be unnecessary in theory, its the same object
                            //((DataGridViewImageCell)row.Cells["PreviewColumn"]).Value = bitmap;
                            dataGridView1.Invalidate();
                        }
                        _eventsHelper.Fire(UpdatedEvent, obj);
                        break;
                    }
                }


            }
        }
        //
        // Force the event to get called on the proper thread.  The DataGridView complains if you try
        //  to use it on the wrong thread.
        //
        public void iAssetManaged_UpdateChangedEvent(IAssetManaged obj)
        {
            IAssetManagedHandler newEvent = new IAssetManagedHandler(iAssetManaged_UpdateChangedEvent_thisThread);
            object[] args = new object[1];
            args[0] = obj;
            //
            // We need to make sure these methods are executed on the correct thread.
            //
            try
            {
                if (this.InvokeRequired)
                    this.Invoke(newEvent, args);
                else
                    newEvent(obj);
            }
            catch { }

        }
        #endregion

        //
        // Selection changed event which gets fired when the selection of the data grid view changes.
        //  This in turn fires another event updating controls that might want to know that the selection
        //  has changed.
        //

        private void dataGridView1_SelectionChanged(object sender, EventArgs e)
        {
            try
            {
                _eventsHelper.Fire(SelectedEvent, GetSelected());
            }
            catch { }
            
            if (assetMan != null)
            {

                if (dataGridView1.SelectedRows.Count > 0 &&
                        dataGridView1.SelectedRows[0].Cells["DataColumn"].Value != null)
                {
                    LayerProxy lay = (LayerProxy)dataGridView1.SelectedRows[0].Cells["DataColumn"].Value;
                    populateDrawables();
                    setActiveDrawables(lay);
                    button1.Text = "Actives";
                    //activeDrawablesDisplayed = false;
                }
            }          
        }

        //
        // Edit the name of cell
        //  This renames the object whose text field was just changed in the data grid view.
        //
        private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (assetMan != null)
            {
                if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex] == dataGridView1.Rows[e.RowIndex].Cells["NameCol"])
                {
                    IAssetManaged obj = (IAssetManaged)dataGridView1.Rows[e.RowIndex].Cells["DataColumn"].Value;
                    if (obj != null)
                    {
                        //obj.BeginManipulation();
                        obj.SetName((String)dataGridView1.Rows[e.RowIndex].Cells["NameCol"].Value);
                        //obj.EndManipulation();
                    }
                }
            }
        }

        // 
        // Key up
        //  - Check for delete key hit to delete selected items
        //
        private void dataGridView1_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                List<IAssetManaged> list = GetSelected();
                foreach (IAssetManaged obj in list)
                {
                    assetMan.Remove(obj);
                }
                e.Handled = true;
            }
        }

        // 
        // Key down
        //  Check for F2 key hit to begin edit
        //
        private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F2)
            {
                dataGridView1.BeginEdit(true);
                e.Handled = true;
            }
            if ((e.KeyCode == Keys.Return) || (e.KeyCode == Keys.Enter))
            {
                dataGridView1.BeginEdit(true);
                e.Handled = true;
            }
        }

        //
        // Cell Double Click
        //  Begin editing on double click in a cell
        //
        private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (dataGridView1.Rows.Count > 0)
                dataGridView1.BeginEdit(true);
        }


        public void UserControl1_SelectedEvent(IList<IAssetManaged> items)
        {

            if (dataGridView1.Rows.Count == 0)
            {
                dataGridView2.Rows.Clear();
                dataGridView2.Invalidate();
            }
            //
            // Unsubscribe from the update event of the old layer
            // Subscribe to the update event of the new layer
            //
            if (layer != null)
            {
                layer.RemoveChangingEventHandler(UpdatedEvent);
            }
            if (items.Count > 0)
            {
                layer = (LayerProxy)items[0];
                UpdatedEvent = new IAssetManagedHandler(layer_UpdatedEvent);
                layer.AddChangingEventHandler(UpdatedEvent);
                //layer_UpdatedEvent(layer);
                //populateDrawables();
                //setActiveDrawables(layer);
                //button1.Text = "Actives";

            }
            
            
        }

        public void layer_UpdatedEvent(IAssetManaged obj)
        {
            _eventsHelper.Fire(ChangedEvent, obj);
        }

        public void UserControl1_UpdatedEvent(IAssetManaged obj)
        {
            _eventsHelper.Fire(ChangedEvent, obj);
        }

        #region ToolStrip Menu
        //
        // Gets a layer from the template list given its name
        //  or returns null if it doesn't exist.
        //
        private LayerProxy GetTemplate(String name)
        {
            foreach (LayerProxy lay in templates)
            {
                if (lay.Name == name)
                {
                    return lay;
                }
            }
            return null;
        }

        private void CreateNewFromTemplate(object sender, EventArgs e)
        {
            if (sender.GetType() == typeof(ToolStripMenuItem))
            {
                String name = ((ToolStripMenuItem)sender).Text;
                LayerProxy layer = GetTemplate(name);
                if (layer != null)
                {

                    IAssetManaged obj = assetMan.Add((IAssetManaged)layer);
                    //SelectOneItem(obj);
                }
            }

            
        }
        static int count = 0;
        private void newButton_Clicked(object sender, EventArgs e)
        {
            //layerWOptionsToolStripMenuItem_Click(sender, e);
            string name = "Layer" + count.ToString();
            count++;
            string fboName = name + "FBO";
            string textureName = name + "Texture";
            string materialName = name + "Material";
            LayerTextureProxy layerTexture = new LayerTextureProxy(textureName, 1024, 1024);
            AssetManager.Instance.Add(layerTexture); 
            FrameBufferObjectProxy fbo = new FrameBufferObjectProxy(fboName, layerTexture);
            AssetManager.Instance.Add(fbo);
            MaterialProxy material = new MaterialProxy(materialName);
            IRasterOps rops = material.Compositor;
            rops.Blending = BlendMode.TRANSPARENT;
            rops.DepthTest = DepthMode.OFF;
            material.Compositor = rops;
            AssetManager.Instance.Add(material);
            material.Shader = AssetManager.Instance.Find(typeof(IShaderProgram), "ModulateTexture") as IShaderProgram;
            material.UniformVariableValues["texture"][0].Sampler = layerTexture;
            LayerProxy layer = new LayerProxy(name, fbo);
            layer.Material = material;
            ICamera camera = AssetManager.Instance.Find(typeof(ICamera), "MainCamera") as ICamera;
            if (camera != null)
            {
                layer.Camera = camera;
            }
            AssetManager.Instance.Add(layer);
            //SelectOneItem(layer);
            //populateDrawables();

        }


        private void layerWOptionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LayerProxy newLayer = new LayerProxy("New Layer", null);
            LayerConfigDialog layerDialog = new LayerConfigDialog(newLayer);
            if (layerDialog.ShowDialog() == DialogResult.OK)
            {
                AssetManager.Instance.Add(newLayer);
            }
        }
        private void openButton_Clicked(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                LayerProxy layer = LayerProxy.LoadFromFile(openFileDialog1.FileName);
                if (layer != null)
                {
                    IAssetManaged obj = assetMan.Add(layer);
                    // check for duplicate
                    if (obj == layer)
                    {
                        // add the new item to the template list and the template drop down if it doesn't
                        //  already exist
                        if (GetTemplate(layer.Name) == null)
                        {
                            templates.Add((LayerProxy)obj);
                            BuiltTemplateDropDown();
                        }
                    }
                }
            }
        }

        private void saveButton_Clicked(object sender, EventArgs e)
        {
            if (GetSelected().Count > 0)
            {
                LayerProxy obj = (LayerProxy)GetSelected()[0];
                if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    obj.SaveToFile(saveFileDialog1.FileName);
                }
            }
        }

        private void removeButton_Clicked(object sender, EventArgs e)
        {
            List<IAssetManaged> list = GetSelected();
            foreach (IAssetManaged obj in list)
            {
                assetMan.Remove(obj);
            }
        }
        #endregion



        private List<LayerProxy> getCurrentLayers()
        {
            List<LayerProxy> list = new List<LayerProxy>();
            List<IAssetManaged> list2 = assetMan.FindAll(typeof(LayerProxy));
            foreach (IAssetManaged obj in list2)
                list.Add((LayerProxy)obj);
            return list;
        }

        private void populateDrawables()
        {
            dataGridView2.Rows.Clear();
            List<IDrawable> listDraw = new List<IDrawable>();
            List<IAssetManaged> list2 = assetMan.FindAll(typeof(IDrawable));
            foreach (IAssetManaged obj in list2)
            {
                if(!(obj is LayerProxy))
                    listDraw.Add((IDrawable)obj);
            }
            foreach (IDrawable draw in listDraw)
            {
                // Populate the datagridview2
                int row = dataGridView2.Rows.Add();
                dataGridView2.Rows[row].Cells["DatColumn"].Value = draw;
                dataGridView2.Rows[row].Cells["DrawablesColumn"].Value = draw.ToString();
                dataGridView2.Rows[row].Cells["listColumn"].Value = false;

            }

            dataGridView1.Invalidate();
            
                        
            // Set the datagridview1 image column to the bitmap


        }

        private void dataGridView2_MouseEnter(object sender, DataGridViewCellEventArgs e)
        {
            //if (!e.ColumnIndex.Equals(2)) return;

        }

        private void dataGridView2_SelectionChanged(object sender, EventArgs e)
        {

        }

        private void dataGridView1_RowAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {


        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

            if (e.ColumnIndex == 0 && e.RowIndex >= 0)
            {
                bool val = (bool)dataGridView1.Rows[e.RowIndex].Cells["CheckColumn"].Value;
                dataGridView1.Rows[e.RowIndex].Cells["CheckColumn"].Value = !val;

                //dataGridView1.Rows[e.RowIndex].Cells["SelectColumn"].ValueType = DataGridViewCheckBoxCell;
                LayerProxy obj = (LayerProxy)dataGridView1.Rows[e.RowIndex].Cells["DataColumn"].Value;
                obj.Active = !val; 
                dataGridView1.Rows[e.RowIndex].Cells["PreviewColumn"].Value = obj.Image;
            }
        }


        private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            //if (dataGridView1.Columns[e.ColumnIndex].Name == "CheckColumn")
            //{
            //    bool val = (bool)dataGridView1.Rows[e.RowIndex].Cells["CheckColumn"].Value;
            //    dataGridView1.Rows[e.RowIndex].Cells["CheckColumn"].Value = !val;

            //    //dataGridView1.Rows[e.RowIndex].Cells["SelectColumn"].ValueType = DataGridViewCheckBoxCell;
            //    LayerProxy obj = (LayerProxy)dataGridView1.Rows[e.RowIndex].Cells["DataColumn"].Value;
            //    obj.Active = !val;
            //    //dataGridView1.Rows[e.RowIndex].Cells["PreviewColumn"].Value = obj.Image;
            //    dataGridView1.Invalidate();
            //}
        }

        private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
        {
            if (dataGridView1.IsCurrentCellDirty)
            {
                dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
            }
        }

        private void dataGridView2_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 3 && e.RowIndex>=0)
            {
                bool val = (bool)dataGridView2.Rows[e.RowIndex].Cells["listColumn"].Value;
                dataGridView2.Rows[e.RowIndex].Cells["listColumn"].Value = !val;
                IDrawable obj = (IDrawable)dataGridView2.Rows[e.RowIndex].Cells["DatColumn"].Value;
                
                // Get the currently selected layer
                List<IAssetManaged> list =  GetSelected();
                if (list.Count > 0)
                {
                    LayerProxy layerProxy = (LayerProxy)list[0];
                    
                    // Add or remove from the drawables list of the selected layer in dataGridView1
                    if ( val == false && !layerProxy.Drawables.Contains(obj))
                    {
                        layerProxy.addDrawableProxy(obj);
                    }
                    else if (val == true)
                    {
                        layerProxy.removeDrawableProxy(obj);
                    }
                    
                }
                //_eventsHelper.Fire(UpdatedEvent, obj);
            }
        }
        private void setActiveDrawables(LayerProxy layerProxy)
        {
            foreach (DataGridViewRow row in dataGridView2.Rows)
            {
                IDrawable iDraw = (IDrawable)row.Cells["DatColumn"].Value;
                if (layerProxy.Drawables.Contains(iDraw))
                {
                    row.Cells["listColumn"].Value = true;
                }
            }
        }

        private void clearDrawables()
        {
            foreach (DataGridViewRow row in dataGridView2.Rows)
            {
                row.Cells["listColumn"].Value = false;
            }
        }

        bool activeDrawablesDisplayed = false;
        private void button1_Click(object sender, EventArgs e)
        {
            List<IAssetManaged> list = GetSelected();
            if (list.Count > 0)
            {
                LayerProxy layerProxy = (LayerProxy)list[0];

                if (!activeDrawablesDisplayed)
                {
                    button1.Text = "Show All";
                    dataGridView2.Rows.Clear();
                    // Get the currently selected layer


                    foreach (IDrawable iDraw in layerProxy.Drawables)
                    {
                        int row = dataGridView2.Rows.Add();
                        dataGridView2.Rows[row].Cells["DatColumn"].Value = (IDrawable)iDraw;
                        dataGridView2.Rows[row].Cells["DrawablesColumn"].Value = iDraw.ToString();
                        dataGridView2.Rows[row].Cells["listColumn"].Value = true;
                    }

                }
                else
                {
                    button1.Text = "Actives";
                    // Populate the drawables
                    populateDrawables();
                    setActiveDrawables(layerProxy);
                }
                dataGridView2.Invalidate();
                activeDrawablesDisplayed = !activeDrawablesDisplayed;
            }
        }

        #region Drag and Drop Support
        private Rectangle dragBoxFromMouseDown;
        private int rowIndexFromMouseDown;
        private int rowIndexOfItemUnderMouseToDrop;


        private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
        {
            if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
            {
                // If the mouse moves outside the rectangle, start the drag.
                if (dragBoxFromMouseDown != Rectangle.Empty &&
                    !dragBoxFromMouseDown.Contains(e.X, e.Y))
                {

                    // Proceed with the drag and drop, passing in the list item.                    
                    if (rowIndexFromMouseDown >= 0)
                    {
                        DragDropEffects dropEffect = dataGridView1.DoDragDrop(
                        dataGridView1.Rows[rowIndexFromMouseDown],
                        DragDropEffects.Move);
                    }
                }
            }

        }

        private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
        {
            // Get the index of the item the mouse is below.
            rowIndexFromMouseDown = dataGridView1.HitTest(e.X, e.Y).RowIndex;

            if (rowIndexFromMouseDown != -1)
            {
                // Remember the point where the mouse down occurred. 
                // The DragSize indicates the size that the mouse can move 
                // before a drag event should be started.                
                Size dragSize = SystemInformation.DragSize;

                // Create a rectangle using the DragSize, with the mouse position being
                // at the center of the rectangle.
                dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2),
                                                               e.Y - (dragSize.Height / 2)),
                                    dragSize);
            }
            else
                // Reset the rectangle if the mouse is not over an item in the ListBox.
                dragBoxFromMouseDown = Rectangle.Empty;
        }

        private void dataGridView1_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }

        private void dataGridView1_DragDrop(object sender, DragEventArgs e)
        {
            // The mouse locations are relative to the screen, so they must be 
            // converted to client coordinates.
            Point clientPoint = dataGridView1.PointToClient(new Point(e.X, e.Y));

            // Get the row index of the item the mouse is below. 
            rowIndexOfItemUnderMouseToDrop =
                dataGridView1.HitTest(clientPoint.X, clientPoint.Y).RowIndex;

            // If the drag operation was a move then remove and insert the row.
            if (e.Effect == DragDropEffects.Move && rowIndexOfItemUnderMouseToDrop>=0)
            {
                DataGridViewRow rowToMove = e.Data.GetData(
                    typeof(DataGridViewRow)) as DataGridViewRow;
                dataGridView1.Rows.RemoveAt(rowIndexFromMouseDown);
                dataGridView1.Rows.Insert(rowIndexOfItemUnderMouseToDrop, rowToMove);

                //Change the only viewProxy's layer ordering
                ILayer lay = viewProxies[0].Layers[rowIndexFromMouseDown];
                viewProxies[0].Layers.RemoveAt(rowIndexFromMouseDown);
                List<ILayer> new_list = viewProxies[0].Layers;
                new_list.Insert(rowIndexOfItemUnderMouseToDrop, lay);
                viewProxies[0].Layers = new_list;
            }
        }


        private Rectangle dragBoxFromMouseDown2;
        private int rowIndexFromMouseDown2;
        private int rowIndexOfItemUnderMouseToDrop2;

        private void dataGridView2_MouseDown(object sender, MouseEventArgs e)
        {
            // Get the index of the item the mouse is below.
            rowIndexFromMouseDown2 = dataGridView2.HitTest(e.X, e.Y).RowIndex;

            if (rowIndexFromMouseDown2 != -1)
            {
                // Remember the point where the mouse down occurred. 
                // The DragSize indicates the size that the mouse can move 
                // before a drag event should be started.                
                Size dragSize = SystemInformation.DragSize;

                // Create a rectangle using the DragSize, with the mouse position being
                // at the center of the rectangle.
                dragBoxFromMouseDown2 = new Rectangle(new Point(e.X - (dragSize.Width / 2),
                                                               e.Y - (dragSize.Height / 2)),
                                    dragSize);
            }
            else
                // Reset the rectangle if the mouse is not over an item in the ListBox.
                dragBoxFromMouseDown2 = Rectangle.Empty;
        }

        private void dataGridView2_MouseMove(object sender, MouseEventArgs e)
        {
            if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
            {
                // If the mouse moves outside the rectangle, start the drag.
                if (dragBoxFromMouseDown2 != Rectangle.Empty &&
                    !dragBoxFromMouseDown2.Contains(e.X, e.Y))
                {

                    // Proceed with the drag and drop, passing in the list item.                    
                    if (rowIndexFromMouseDown2 >= 0)
                    {
                        DragDropEffects dropEffect = dataGridView2.DoDragDrop(
                        dataGridView2.Rows[rowIndexFromMouseDown2],
                        DragDropEffects.Move);
                    }
                }
            }
        }

        private void dataGridView2_DragDrop(object sender, DragEventArgs e)
        {
            // The mouse locations are relative to the screen, so they must be 
            // converted to client coordinates.
            Point clientPoint = dataGridView2.PointToClient(new Point(e.X, e.Y));

            // Get the row index of the item the mouse is below. 
            rowIndexOfItemUnderMouseToDrop2 =
                dataGridView2.HitTest(clientPoint.X, clientPoint.Y).RowIndex;

            // If the drag operation was a move then remove and insert the row.
            if (e.Effect == DragDropEffects.Move && rowIndexOfItemUnderMouseToDrop2 >= 0)
            {
                DataGridViewRow rowToMove = e.Data.GetData(
                    typeof(DataGridViewRow)) as DataGridViewRow;
                dataGridView2.Rows.RemoveAt(rowIndexFromMouseDown2);
                dataGridView2.Rows.Insert(rowIndexOfItemUnderMouseToDrop2, rowToMove);

                // Get the current layer and change the order of drawables in it.
                List<IAssetManaged> list = GetSelected();
                if (list.Count >0)
                {
                    LayerProxy lay = list[0] as LayerProxy;
                    IDrawable draw = lay.Drawables[rowIndexFromMouseDown2];
                    lay.Drawables.RemoveAt(rowIndexFromMouseDown2);
                    List<IDrawable> new_list = lay.Drawables;
                    new_list.Insert(rowIndexOfItemUnderMouseToDrop2, draw);
                    lay.Drawables = new_list;
                }

            }
        }

        private void dataGridView2_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }
        #endregion    
    }
}
